﻿using Common;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using System.Web.Script.Serialization;
using System.Web.Security;
using System.Web.SessionState;

namespace WebGrabber.Web
{
    public class Global : System.Web.HttpApplication
    {
        private static string GetRemoteHtml(string url, Encoding encoding)
        {
            try
            {
                if (CacheUtil.Exist(url))
                {
                    return CacheUtil.Get<string>(url);
                }
                WebClient client = new WebClient();
                StreamReader reader = new StreamReader(client.OpenRead(url), encoding);
                string html = reader.ReadToEnd();
                reader.Close();
                CacheUtil.Set(url, html);
                return html;
            }
            catch (Exception e)
            {
                return e.Message;
            }
        }

        /// <summary>
        /// 提取当前域名(带http://)
        /// </summary>
        /// <returns></returns>
        public static string GetSiteDomain()
        {
            string uri = HttpContext.Current.Request.Url.AbsoluteUri;
            string domain = Regex.Replace(uri, "(.+?)://(.+?)/.*?$", "$1://$2", RegexOptions.IgnoreCase);
            return domain;
        }

        public static string GetCurrentPath()
        {
            string uri = HttpContext.Current.Request.Url.AbsoluteUri;
            string path = Regex.Replace(uri, "(.+?)://(.+?)(/.*)(.*?)$", "$3", RegexOptions.IgnoreCase);
            if (path.Contains("."))
            {
                path = path.Substring(0, path.LastIndexOf("/") + 1);
            }
            return path.TrimEnd('/') + "/";
        }

        public static string AddAbsoluteUrl(string domain, string currentPath, string source, List<Hashtable> lstAttrRegex)
        {
            source = Regex.Replace(source, "<(img|script|input)([^>]*?)src=(\"|')(/)([^>]*?)(\"|')([^>]*?)>", "<$1$2 src=\"" + domain + "/$5\"$7>");
            source = Regex.Replace(source, "<(img|script|input)([^>]*?)src=(\"|')(?!(http://|https://))([^>]*?)(\"|')([^>]*?)>", "<$1$2 src=\"" + domain + currentPath + "/$4\"$6>", RegexOptions.IgnoreCase);
            source = Regex.Replace(source, "<link.*?href=(\"|')(/)(.*?)(\"|')(.*?)>", "<link href=\"" + domain + "/$3\"$5>", RegexOptions.IgnoreCase);
            source = Regex.Replace(source, "<link.*?href=(\"|')(?!(http://|https://))(.*?)(\"|')(.*?)>", "<link href=\"" + domain + currentPath + "/$2\"$4>", RegexOptions.IgnoreCase);
            source = Regex.Replace(source, "<(form[^>]*?)action=(\"|')(/)([^>]*?)(\"|')([^>]*?)>", "<$1 action=\"" + domain + "/$4\"$6>", RegexOptions.IgnoreCase);
            source = Regex.Replace(source, "<(form[^>]*?)action=(\"|')(?!(http://|https://))([^>]*?)(\"|')([^>]*?)>", "<$1 action=\"" + domain + currentPath + "/$3\"$5>", RegexOptions.IgnoreCase);
            //source = Regex.Replace(source, "<([^>]*?)style=(\"|')([^>]*?)background:url\\((?!http://)([^>]*?)\\)([^>]*?)>", " 1:$1 2:$2 3:$3 4:$4 5:$5 6:$6 7:$7");
            source = Regex.Replace(source, "<([^>]*?)style=(\"|')([^>]*?)background:([^>]*?)url\\((?!(http://|https://))([^>]*?)\\)([^>]*?)>", "<$1 style=\"$4background:url(" + domain + "/$6)$7>", RegexOptions.IgnoreCase);
            source = Regex.Replace(source, "<a([^>]*?)href=(\"|')(/)([^>]*?)(\"|')([^>]*?)>", "<a$1 href=\"" + domain + "/$4\"$6>");
            if (lstAttrRegex.Count() > 0)
            {
                foreach (var item in lstAttrRegex)
                {
                    source = Regex.Replace(source, item["pattern"].ToString(), item["replacement"].ToString(), Convert.ToInt32(item["ignoreCase"]) == 1 ? RegexOptions.IgnoreCase : RegexOptions.None);
                }
            }
            //替换重复的斜线
            source = Regex.Replace(source, "<([^>]*?)([^>]*?)(?<!:)(//)([^>]*?)>", "<$1$2/$4>", RegexOptions.IgnoreCase);

            source = source.Replace(domain + "//", domain + "/");
            return source;
        }

        Dictionary<string, string> dicSite
        {
            get
            {
                Dictionary<string, string> dic = CacheUtil.Get<Dictionary<string, string>>("site");
                if (dic == null)
                {
                    string confgStr = FileUtil.Read("~/site.json");
                    dic = new JavaScriptSerializer().Deserialize<Dictionary<string, string>>(confgStr);
                    CacheUtil.Set("site", dic);
                }
                return dic;
            }
        }

        List<Hashtable> attrRegex
        {
            get
            {
                List<Hashtable> list = new List<Hashtable>();
                Hashtable hash = new Hashtable();
                hash["pattern"] = "<(a[^>]*?)rel=(\"|')(/)([^>]*?)(\"|')([^>]*?)>";
                hash["replacement"] = "<$1 rel=\"http://xmldt.dbdy.net$3$4$5>";
                hash["ignoreCase"] = 1;
                list.Add(hash);
                return list;
            }
        }

        List<string> redirectUrl
        {
            get
            {
                List<string> list = new List<string>();
                Hashtable hash = new Hashtable();
                //list.Add("/admin");
                return list;
            }
        }

        protected void Application_Start(object sender, EventArgs e)
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }

        protected void Session_Start(object sender, EventArgs e)
        {

        }

        protected void Application_BeginRequest(object sender, EventArgs e)
        {
            try
            {
                string domain = GetSiteDomain();
                string currentPath = GetCurrentPath();
                string requestPage = Request.RawUrl;
                if (!dicSite.ContainsKey(domain))
                {
                    return;
                }
                string grabUrl = dicSite[domain] + requestPage;

                foreach (var item in redirectUrl)
                {
                    if (item.ToLower() == requestPage.ToLower())
                    {
                        Response.Redirect(dicSite[domain] + requestPage);
                        Response.End();
                    }
                }

                string grabHtml = GetRemoteHtml(grabUrl, Encoding.GetEncoding("utf-8"));
                string html = AddAbsoluteUrl(dicSite[domain], currentPath, grabHtml, attrRegex);
                Response.Write(html);
                Response.End();
            }
            catch (Exception ex)
            {
                throw new Exception("页面抓取失败");
            }
        }

        protected void Application_AuthenticateRequest(object sender, EventArgs e)
        {

        }

        protected void Application_Error(object sender, EventArgs e)
        {

        }

        protected void Session_End(object sender, EventArgs e)
        {

        }

        protected void Application_End(object sender, EventArgs e)
        {

        }
    }
}